Skip to content

ci: auto-close tracked issues when a tracking issue is closed#2993

Merged
thedotmack merged 1 commit into
mainfrom
chore/close-tracked-issues-workflow
Jun 17, 2026
Merged

ci: auto-close tracked issues when a tracking issue is closed#2993
thedotmack merged 1 commit into
mainfrom
chore/close-tracked-issues-workflow

Conversation

@thedotmack

Copy link
Copy Markdown
Owner

What

Adds .github/workflows/close-tracked-issues.yml. When an issue labeled tracking is closed, the workflow reads the issue numbers under that issue's ### Issues section and closes each one, leaving a comment pointing back to the tracker.

This makes the 19 consolidated tracking issues (#2958#2976) actually behave like trackers: close the master → its duplicate reports close automatically.

Why

GitHub's Closes #N keyword only auto-closes on merged PRs/commits, never when an issue is closed. So issue-to-issue consolidation needs this glue.

Behavior

  • Triggers on issues: closed, guarded to issues carrying the tracking label.
  • Parses only the ### Issues block — PRs under ### PRs are intentionally left untouched (those get merged, not closed).
  • Skips anything already closed or that resolves to a PR; one bad reference won't abort the rest.
  • Closes children as completed with a back-reference comment.
  • Includes a workflow_dispatch input for on-demand fan-out close (useful for testing without closing the tracker).

Verification

Ran the extraction regex against the live body of tracker #2959 — it returned exactly the 4 tracked issues (2950, 2896, 2907, 2897) and correctly excluded the 2 related PRs (2536, 2920).

Note: GitHub runs issues-triggered workflows from the file on the default branch, so this only takes effect once merged to main.

🤖 Generated with Claude Code

@greptile-apps

greptile-apps Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

Adds .github/workflows/close-tracked-issues.yml to automatically close all child issues listed under a tracking issue's ### Issues section when the tracker itself is closed. The workflow handles both the automatic issues: closed trigger and a workflow_dispatch path for manual re-runs on already-closed trackers.

  • Trigger & guard: Fires on issues: closed (requires the tracking label) or workflow_dispatch (accepts any issue number but refuses to fan-out if the tracker is still open, preventing accidental bulk-closes).
  • Parsing: Extracts only the ### Issues block using a regex that terminates on any heading level H2–H6+ (#{2,}), leaving the ### PRs block untouched.
  • Fan-out loop: Skips PRs and already-closed issues, posts a back-reference comment, closes each child as completed, and isolates errors per item so one bad reference doesn't abort the rest.

Confidence Score: 5/5

Safe to merge — a single new workflow file that writes only to issues in the same repo, with narrow permissions and clear guard rails on every code path.

The workflow's two previously flagged concerns — the workflow_dispatch open-tracker guard and the heading-level regex — are both addressed in this version. The issues: write / contents: read permission scope is appropriately minimal, the GITHUB_TOKEN never leaves the workflow, and each child-close is wrapped in a try/catch so a single bad reference cannot abort the rest of the fan-out. No logic paths were found that would cause unintended bulk-closes or data loss.

No files require special attention.

Important Files Changed

Filename Overview
.github/workflows/close-tracked-issues.yml New workflow that auto-closes child issues when a tracking-labeled issue is closed; includes workflow_dispatch for manual re-runs, a guard that refuses to fan-out while the tracker is still open, PR-skipping logic, idempotent already-closed checks, and per-item error isolation.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant GH as GitHub
    participant WF as Workflow Runner
    participant API as GitHub REST API

    alt issues: closed trigger
        GH->>WF: issue closed event (tracking label required)
        WF->>WF: "tracker = event.issue payload"
    else workflow_dispatch
        GH->>WF: manual dispatch (issue_number input)
        WF->>API: "GET /issues/{issue_number}"
        API-->>WF: tracker data
        WF->>WF: "guard: tracker.state !== 'closed'? exit"
    end

    WF->>WF: "parse ### Issues section (regex)"
    WF->>WF: "extract #NNN references, dedupe, filter self"

    loop for each tracked issue number
        WF->>API: "GET /issues/{n}"
        API-->>WF: target data
        alt is PR
            WF->>WF: skip
        else already closed
            WF->>WF: skip
        else open issue
            WF->>API: "POST /issues/{n}/comments (back-reference)"
            WF->>API: "PATCH /issues/{n} state=closed, reason=completed"
            API-->>WF: success / error (caught, continues)
        end
    end
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant GH as GitHub
    participant WF as Workflow Runner
    participant API as GitHub REST API

    alt issues: closed trigger
        GH->>WF: issue closed event (tracking label required)
        WF->>WF: "tracker = event.issue payload"
    else workflow_dispatch
        GH->>WF: manual dispatch (issue_number input)
        WF->>API: "GET /issues/{issue_number}"
        API-->>WF: tracker data
        WF->>WF: "guard: tracker.state !== 'closed'? exit"
    end

    WF->>WF: "parse ### Issues section (regex)"
    WF->>WF: "extract #NNN references, dedupe, filter self"

    loop for each tracked issue number
        WF->>API: "GET /issues/{n}"
        API-->>WF: target data
        alt is PR
            WF->>WF: skip
        else already closed
            WF->>WF: skip
        else open issue
            WF->>API: "POST /issues/{n}/comments (back-reference)"
            WF->>API: "PATCH /issues/{n} state=closed, reason=completed"
            API-->>WF: success / error (caught, continues)
        end
    end
Loading

Reviews (2): Last reviewed commit: "ci: auto-close tracked issues when a tra..." | Re-trigger Greptile

Comment thread .github/workflows/close-tracked-issues.yml
Comment thread .github/workflows/close-tracked-issues.yml Outdated
Adds a workflow that, when an issue labeled `tracking` is closed, reads
the issue numbers under its "### Issues" section and closes each one with
a back-reference comment. PRs listed under "### PRs" are left untouched.

- Manual workflow_dispatch refuses to fan-out unless the tracker is already
  closed, matching the `issues: closed` invariant (guards against an
  accidental bulk-close on an open issue).
- Section terminator widened to any heading level so a deeper heading inside
  the Issues block can't leak unrelated #refs into the close set.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@thedotmack
thedotmack force-pushed the chore/close-tracked-issues-workflow branch from ed411fa to 43e34c0 Compare June 17, 2026 20:03
@thedotmack
thedotmack merged commit b1dfe1f into main Jun 17, 2026
7 checks passed
@thedotmack
thedotmack deleted the chore/close-tracked-issues-workflow branch June 17, 2026 20:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant